package com.example.calcite.xml;

import org.apache.calcite.schema.Schema;
import org.apache.calcite.schema.impl.AbstractSchema;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import javax.xml.parsers.DocumentBuilderFactory;
import java.io.ByteArrayInputStream;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class DynamicXmlSchema extends AbstractSchema {
    private final String xmlId;
    private final XmlService xmlService;
    private final Map<String, XmlTable> tableMap = new HashMap<>();
    private static final Map<String, Document> xmlCache = new ConcurrentHashMap<>();

    public DynamicXmlSchema(String xmlId, XmlService xmlService) {
        this.xmlId = xmlId;
        this.xmlService = xmlService;
        loadTables();
    }

    private void loadTables() {
        try {
            Document doc = getXmlDocument();
            Element root = doc.getDocumentElement();
            NodeList children = root.getChildNodes();
            
            for (int i = 0; i < children.getLength(); i++) {
                Node node = children.item(i);
                if (node.getNodeType() == Node.ELEMENT_NODE) {
                    String tableName = node.getNodeName();
                    tableMap.put(tableName, new XmlTable(doc, tableName));
                }
            }
        } catch (Exception e) {
            throw new RuntimeException("Error loading tables from XML ID: " + xmlId, e);
        }
    }

    private Document getXmlDocument() throws Exception {
        return xmlCache.computeIfAbsent(xmlId, id -> {
            try {
                String xmlContent = xmlService.getXmlContent(id);
                return DocumentBuilderFactory.newInstance()
                    .newDocumentBuilder()
                    .parse(new ByteArrayInputStream(xmlContent.getBytes()));
            } catch (Exception e) {
                throw new RuntimeException("Error fetching XML for ID: " + id, e);
            }
        });
    }

    @Override
    public Map<String, org.apache.calcite.schema.Table> getTableMap() {
        return new HashMap<>(tableMap);
    }
}